package com.mycompany.delivery.web;

import com.mycompany.delivery.dto.ContactDTO;
import com.mycompany.delivery.dto.DTOState;
import com.mycompany.delivery.dto.DeliveryDTO;
import com.mycompany.delivery.dto.UserDTO;
import com.mycompany.delivery.servicelayer.ContactService;
import com.mycompany.delivery.servicelayer.DeliveryService;
import com.mycompany.delivery.servicelayer.UserService;
import com.mycompany.delivery.validation.DeliverySpringValidator;
import static com.mycompany.delivery.web.DeliveryController.log;
import java.util.ArrayList;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.springframework.web.util.UriComponentsBuilder;
import java.util.List;
import java.util.Locale;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.util.UriUtils;

/**
 *
 *
 * @author Jana Němcová
 */
@Controller
@RequestMapping("/delivery")
public class DeliveryController {

    final static Logger log = LoggerFactory.getLogger(DeliveryController.class);

    @Autowired
    private DeliveryService deliveryService;

    @Autowired
    private ContactService contactServices;

    @Autowired
    private UserService userService;

    @Autowired
    private MessageSource messageSource;

    @ModelAttribute("contacts")
    public List<ContactDTO> allContact() {
        log.debug("allContacts()");
        return contactServices.getAllContacts();
    }
    
      @ModelAttribute("currentCouriers")
    public List<UserDTO> currentCouriers() {
        log.debug("currentCouriers()");
        return userService.getAllCouriers();
    }

    @ModelAttribute("states")
    public DTOState[] states() {
        log.debug("states()");
        return DTOState.values();
    }

    @ModelAttribute("undeliveredDeliveries")
    public List<DeliveryDTO> allUndeliveredDeliveries() {
        log.debug("allDeliveriesInUnprocessedState()");
        return deliveryService.getDeliveriesInUnprocessedState();

    }
    
     @ModelAttribute("processedDeliveries")
    public List<DeliveryDTO> allProcessedDeliveries() {
        log.debug("allDeliveriesInProcessedState()");
        return deliveryService.getDeliveriesInProcessedState();
    }

    @ModelAttribute("deliveriesWithoutCourier")
    public List<DeliveryDTO> deliveriesWithoutCourier() {
        log.debug("deliveriedWithoutCourier()");
        return deliveryService.getDeliveriesWithoutCourier();
    }

    /**
     * form na přidávání recievera
     * @param model
     * @return 
     */
    @RequestMapping(value = "/formR", method = RequestMethod.GET)
    public String rece(Model model) {
        log.debug("rece()");
        model.addAttribute("delivery", new DeliveryDTO());
        return "delivery/formR";
    }

    /**
     * form n hledání sendera ( na řadu po recieverovy)
     * @return 
     */
    @RequestMapping(value = "/findS/{idd}", method = RequestMethod.POST)
    public String findedS(@PathVariable Long idd, @RequestParam("name") String name, Model model, UriComponentsBuilder builder, Locale locale) {
        String n = name;
        log.debug("atribut1 {} loc {}", name, locale);
        try {
            n = UriUtils.encodePath(name, "UTF-8");
        } catch (Exception ex) {
        }
        log.debug("atribut2 {}", n);
        log.debug("find(model={})", model);

        return "redirect:" + builder.path("/delivery/findS/" + idd + "/" + n).build();
    }

    /**
     * form n hledání sendera ( na řadu po recieverovy)
     * @return 
     */
    @RequestMapping(value = "/findS", method = RequestMethod.GET)
    public String findDefS(Model model) {
        model.addAttribute("string", new String());
        model.addAttribute("contacts", new ArrayList<ContactDTO>());
        log.debug("find(model={})", model);
        return "delivery/formS";
    }

    /**
     * form n hledání sendera ( na řadu po recieverovy), vyhledávání jména
     * @return 
     */
    @RequestMapping(value = "/findS/{idd}/{name}", method = RequestMethod.GET)
    public String findDefS(@PathVariable Long idd, @PathVariable String name, Model model) {
        model.addAttribute("string", new String());
        model.addAttribute("idd", idd);
        model.addAttribute("contacts", contactServices.findContactBySurname(name));
        log.debug("find(model={})", model);
        return "delivery/formS";
    }

    /**
     * form na hledání recievera
     * @return 
     */
    @RequestMapping(value = "/find", method = RequestMethod.GET)
    public String findDef(Model model) {
        model.addAttribute("string", new String());
        model.addAttribute("contacts", new ArrayList<ContactDTO>());
        log.debug("find(model={})", model);
        return "delivery/formR";
    }

     /**
     * form na hledání recievera hledání dle jmena
     * @return 
     */
    @RequestMapping(value = "/find/{name}", method = RequestMethod.GET)
    public String findDef(@PathVariable String name, Model model) {
        model.addAttribute("string", new String());
        model.addAttribute("contacts", contactServices.findContactBySurname(name));
        log.debug("find(model={})", model);
        return "delivery/formR";
    }

    
    @RequestMapping(value = "/nova/{id}", method = RequestMethod.POST)
    public String newContact(@PathVariable Long id, Model model, UriComponentsBuilder builder) {
        return "redirect:" + builder.path("/delivery/nova/" + id).build();
    }

    @RequestMapping(value = "/nova/{id}", method = RequestMethod.GET)
    public String newContact2(@PathVariable Long id, Model model, UriComponentsBuilder builder) {
        log.debug("listNova()");
        model.addAttribute("idd", id);
        return "delivery/formS";
    }

    @RequestMapping(value = "/nova/{idd}/{id}", method = RequestMethod.POST)
    public String newContactFinal(@PathVariable Long idd, @PathVariable Long id, Model model, UriComponentsBuilder builder) {
        return "redirect:" + builder.path("/delivery/nova/" + idd + "/" + id).build();
    }

    /**
     * sender a reciever vybrán přidávání ceny, poznámky, zaplacení
     * @return 
     */
    @RequestMapping(value = "/nova/{idd}/{id}", method = RequestMethod.GET)
    public String newContactFinal2(@PathVariable Long idd, @PathVariable Long id, Model model, UriComponentsBuilder builder) {
        ContactDTO c = contactServices.find(idd);
        ContactDTO c2 = contactServices.find(id);
        log.debug("listNova final()");
        DeliveryDTO d = new DeliveryDTO();
        model.addAttribute("delivery", d);
        model.addAttribute("idd", idd);
        model.addAttribute("id", id);
        log.debug(idd.toString() + "::" + id.toString() + ".." + d.getId());
        return "delivery/nova";

    }

    @RequestMapping(value = "/find", method = RequestMethod.POST)
    public String finded(@RequestParam("name") String name, Model model, UriComponentsBuilder builder, Locale locale) {
        String n = name;
        log.debug("atribut1 {} loc {}", name, locale);
        try {
            n = UriUtils.encodePath(name, "UTF-8");
        } catch (Exception ex) {
        }
        log.debug("atribut2 {}", n);
        log.debug("find(model={})", model);

        return "redirect:" + builder.path("/delivery/find/" + n).build();
    }

   

  

    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public String list(Model model) {
        log.debug("list()");
        model.addAttribute("delivery", new DeliveryDTO());
        return "delivery/list";
    }

    @RequestMapping(value = "/nova", method = RequestMethod.GET)
    public String listNovy(Model model) {
        log.debug("listNova()");
        model.addAttribute("delivery", new DeliveryDTO());
        return "delivery/nova";
    }

    @RequestMapping(value = "/add/{id}", method = RequestMethod.POST)
    public String addCourier(@PathVariable long id, Model model) {
        log.debug("addCourier()");
        model.addAttribute("delivery", id);
        return "delivery/formC";
    }

    @RequestMapping(value = "/add/{delivery}/{id}", method = RequestMethod.POST)
    public String addCourier2(@PathVariable long delivery, @PathVariable long id, Model model, UriComponentsBuilder uriBuilder) {
        log.debug("addCourier2()");
        DeliveryDTO del = deliveryService.find(delivery);
        UserDTO u = userService.findCourier(id);
        deliveryService.addDeliveryToCourier(del, u);
        return "redirect:" + uriBuilder.path("/delivery/list2").build();
    }

    @RequestMapping(value = "/list2", method = RequestMethod.GET)
    public String list2(Model model) {
        log.debug("list2()");
        model.addAttribute("delivery", new DeliveryDTO());
        return "delivery/list2";
    }

    @RequestMapping(value = "/delete/{id}", method = RequestMethod.POST)
    public String delete(@PathVariable long id, RedirectAttributes redirectAttributes, Locale locale, UriComponentsBuilder uriBuilder) {
        log.debug("delete({})", id);
        DeliveryDTO del = deliveryService.find(id);
        deliveryService.remove(del);
        redirectAttributes.addFlashAttribute(
                "message",
                messageSource.getMessage("delivery.delete.message", new Object[]{del.getId()}, locale)
        );
        return "redirect:" + uriBuilder.path("/delivery/list").build();
    }

    @RequestMapping(value = "/update/{id}", method = RequestMethod.GET)
    public String update_form(@PathVariable long id, Model model) {
        DeliveryDTO del = deliveryService.find(id);
        model.addAttribute("delivery", del);
        log.debug("update_form(model={})", model);
        return "delivery/edit";
    }

    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.addValidators(new DeliverySpringValidator());
    }

    @RequestMapping(value = "/update", method = RequestMethod.POST)
    public String update(@Valid @ModelAttribute DeliveryDTO del, BindingResult bindingResult, RedirectAttributes redirectAttributes, UriComponentsBuilder uriBuilder, Locale locale) {
        log.debug("update(locale={}, delivery={})", locale, del);
        if (bindingResult.hasErrors()) {
            log.debug("binding errors");
            for (ObjectError ge : bindingResult.getGlobalErrors()) {
                log.debug("ObjectError: {}", ge);
            }
            for (FieldError fe : bindingResult.getFieldErrors()) {
                log.debug("FieldError: {}", fe);
            }
            return del.getId() == null ? "delivery/list" : "delivery/edit";
        }
        if (del.getId() == null) {
            deliveryService.create(del);
            redirectAttributes.addFlashAttribute(
                    "message",
                    messageSource.getMessage("delivery.add.message", new Object[]{del.getId()}, locale)
            );
        } else {
            DeliveryDTO curr = deliveryService.find(del.getId());
            curr.setNotes(del.getNotes());
            curr.setPaid(del.isPaid());
            curr.setPrice(del.getPrice());

            deliveryService.update(curr);
            redirectAttributes.addFlashAttribute(
                    "message",
                    messageSource.getMessage("delivery.updated.message", new Object[]{del.getId()}, locale)
            );
        }
        return "redirect:" + uriBuilder.path("/delivery/list").build();
    }
  

    @RequestMapping(value = "/update/{idd}/{id}", method = RequestMethod.POST)
    public String create(@PathVariable Long idd, @PathVariable Long id, @Valid @ModelAttribute DeliveryDTO del, BindingResult bindingResult, RedirectAttributes redirectAttributes, UriComponentsBuilder uriBuilder, Locale locale) {
        log.debug("update(locale={}, delivery={})", locale, del);
        if (bindingResult.hasErrors()) {
            log.debug("binding errors");
            for (ObjectError ge : bindingResult.getGlobalErrors()) {
                log.debug("ObjectError: {}", ge);
            }
            for (FieldError fe : bindingResult.getFieldErrors()) {
                log.debug("FieldError: {}", fe);
            }
         redirectAttributes.addFlashAttribute(
                    "message",
                    messageSource.getMessage("price.null", new Object[]{}, locale));
            return "redirect:" + uriBuilder.path("/delivery/nova/"+idd + "/"+id).build();
        }
        
        del.setReceiver(contactServices.find(idd));
        del.setSender(contactServices.find(id));
        del.setState(DTOState.UNPROCESSED);
        if (del.getId() == null) {
            del.setReceiver(contactServices.find(idd));
            del.setSender(contactServices.find(id));
            del.setSendingDate(new Date());
            deliveryService.create(del);
            
            
            
            Authentication auth = SecurityContextHolder.getContext().getAuthentication();
            if (auth != null) {
                String name = auth.getName(); 
                 for (GrantedAuthority s : auth.getAuthorities()) {
                     if("ROLE_EMPL".equals(s.getAuthority())){
                         UserDTO u = userService.findUserByLogin(name);
                  //       if(u.getClass()==EmployeeDTO.class)
                     //    {}
                         try {
                         deliveryService.addDeliveryToEmployee(del, u);
                         }
                         catch(Exception e) {
                             List<UserDTO> userDTOall = userService.getAllEmployees();
                             if(userDTOall.size()>0) {
                                   deliveryService.addDeliveryToEmployee(del, userDTOall.get(0));
                             }
                         }
                        }
                    }
             }
            
            redirectAttributes.addFlashAttribute(
                    "message",
                    messageSource.getMessage("delivery.add.message", new Object[]{del.getId()}, locale)
            );
        } else {
            del.setSendingDate(new Date());
            Authentication auth = SecurityContextHolder.getContext().getAuthentication();
            if (auth != null) {
                String name = auth.getName(); 
                 for (GrantedAuthority s : auth.getAuthorities()) {
                     if("ROLE_EMPL".equals(s.getAuthority())){
                         UserDTO u = userService.findUserByLogin(name);
                  //       if(u.getClass()==EmployeeDTO.class)
                     //    {}
                         del.setEmployee(u.getId());
                        }
                    }
             }
            deliveryService.update(del);
            redirectAttributes.addFlashAttribute(
                    "message",
                    messageSource.getMessage("delivery.updated.message", new Object[]{del.getId()}, locale)
            );
        }
        return "redirect:" + uriBuilder.path("/delivery/list2").build();
    }
    
     
}
